import os
import gdata
import gdata.docs
import gdata.docs.service
import inspect
from tmpfiles import DocHandler
from writers import SimpleWriter
from getpass import getpass
import readline

def PrintFeed(feed):
    """Prints out the contents of a feed to the console."""
    if not feed.entry:
        print 'No entries in feed.\n'
    for entry in feed.entry:
        print '%s %s %s' % (entry.title.text.encode('UTF-8'), entry.GetDocumentType(), entry.resourceId.text)

    
class PublisherClient(object):
    def __init__(self, login = None):
        self.login = login
        self.gd_client = gdata.docs.service.DocsService(source='test-gpublish-v1')
        self.connect()

    def manage_dirs(self, basedir, currentdir):
        # directory management 
        # checks for the gpublish directories on googledocs, if they don't exist, create them

        self.basedir = basedir
        self.currentdir = currentdir

        self.directorylist = {}
        
        self.BFfeed = self.check_and_create(self.basedir)
        self.CFfeed = self.exists(self.currentdir)
        if not self.CFfeed:
            self.CFfeed = self.mkdir(self.currentdir, self.BFfeed)

    def connect(self):
        password = getpass('gDoc password ['+self.login+']: ')
        self.gd_client.ClientLogin(self.login, password)
        
        
    def mkdir(self, name, folder = None):
        if folder:
            folder_entry = self.gd_client.CreateFolder(name, folder)
        else:
            folder_entry = self.gd_client.CreateFolder(name)
        return folder_entry

    def check_and_create(self, name):
        '''
        Checks that a name exists, if so returns the entry, otherwise create and return the entry
        '''
        res = self.exists(name)
        if res == None:
            res = self.mkdir(name)
        return res
    
    def exists(self, folder):
        q = gdata.docs.service.DocumentQuery(categories=['folder'], params={'showfolders': 'true'})
        feed = self.gd_client.Query(q.ToUri())
        for entry in feed.entry:
            if folder == entry.title.text:
                return entry
        return None

    def print_alldocs(self):
        q = gdata.docs.service.DocumentQuery(categories=['documents'], params={'showfolders': 'true'})
        feed = self.gd_client.Query(q.ToUri())
        print feed
        PrintFeed(feed)

    def print_folderlist(self):
        q = gdata.docs.service.DocumentQuery(categories=['folder'], params={'showfolders': 'true'})
        feed = self.gd_client.Query(q.ToUri())
        PrintFeed(feed)

    def print_documentlist(self):
        feed = self.gd_client.GetDocumentListFeed()
        PrintFeed(feed)
        
    def remotefile_exists(self, remotefile, folder = None):
        # todo, add check for the good folder
        q = gdata.docs.service.DocumentQuery()
        q['title'] = remotefile
        q['title-exact'] = 'true'
        if folder:
            q['folder'] = folder
            q['folder-exact'] = 'true'
        feed = self.gd_client.Query(q.ToUri())
        if len(feed.entry) > 0:
            return feed
        else:
            return None
        
    def upload(self, localfile, remotefile):
        ms = gdata.MediaSource(file_path=localfile, 
                               content_type=gdata.docs.service.SUPPORTED_FILETYPES['RTF'])

        remotefile_feed = self.remotefile_exists(remotefile, folder = self.currentdir)

        if remotefile_feed:
            # replace file
            if len(remotefile_feed.entry)>0:
                print 'Multiple remote files, replacing first occurence'
            remotefile_entry = remotefile_feed.entry[0]
            created_entry = self.gd_client.Put(ms, remotefile_entry.GetEditMediaLink().href)
        else:
            # create file
            created_entry = self.gd_client.Upload(ms, remotefile, folder_or_uri=self.CFfeed)

        print 'Document now accessible online at:', created_entry.GetAlternateLink().href

def make_rtf(text, imagestr, filename):
    DR = Renderer()

    doc     = Document()
#    ss      = doc.StyleSheet
    section = Section()
    doc.Sections.append( section )
    
    section.append( 'Firstdocument' )
    section.append( text )
    section.append( Paragraph( Image( imagestr, scale_x = 50, scale_y = 50 ) ) )
    f = file(filename, 'wb')
    DR.Write( doc, f)
    f.close()

######################################################################################
# The main publish function
from matplotlib import _pylab_helpers, interactive
import sys
#sys.stdin.flush()

def publish(*args, 
             **kwdargs):
    '''
    Publish the __doc__ and the figures of the current script to google documents.
    
    
    * Arguments *

    '''
    publish = kwdargs.get('publish', True)
    clear = kwdargs.get('clear', False)
    save = kwdargs.get('save', True)
    return_caller = kwdargs.get('return_caller', False)
    remote_directories = kwdargs.get('remote_directories', True)
    verbose = kwdargs.get('verbose', 0)
    login = kwdargs.get('login', None)
    
    if len(args) == 0:
        #in this case fetch the images
        fignames = []
        for i,fig in enumerate(_pylab_helpers.Gcf.get_all_fig_managers()):
            figname = './tmpfig.'+str(i)+'.png'
            fignames.append(figname)
            fig.canvas.figure.savefig(figname)
    else:
        fignames = args[0]

    # traceback trick to get the __doc__ string
    frame = inspect.currentframe()
    basescript = frame.f_back
    if return_caller:
        return basescript
    
    # guess title and text
    tmp = basescript.f_globals['__doc__']
    if tmp == None:
        print 'No docstring found, aborting'
        return
    tmp = tmp.strip('\n')
    tmp = tmp.split('\n')
    doctitle = tmp[0]
    text = ''
    for line in tmp[2:]:
        if line == '':
            line = '\n'
        text += line

    if verbose:
        print 'Publishing document "'+doctitle+'" with text:\n'+text

    handler = DocHandler(clear = clear)
    if not login in [None, '']:
        handler.set_login(login)
    elif handler.login == '_undefined_':
        login = raw_input('gDoc login: ')
        while login == '':
            login = raw_input('gDoc login: ')
        handler.set_login(login)
    # find the name of the base script
    local_tmpfile = os.path.join(handler.client_tmpfolder, 
                            'tmp_file.rtf')

    writer = SimpleWriter(local_tmpfile)
    writer.create_doc(doctitle, text, fignames, save = save)

    if publish:
        publisher = PublisherClient(login = handler.login)
        publisher.manage_dirs(handler.server_basefolder, 
                              handler.server_currentfolder)
        publisher.upload(local_tmpfile, doctitle)
